import {
  toBoolean,
  isPlainObject,
  forEach,
  isEmpty,
  toNumber,
  decode,
  isNotEmpty,
  execScript,
} from '@jecloud/utils';
import Base from './base';
import { FuncFieldTypeEnum } from './func-field-enum';
import { parseEvents } from './util';
export default class FuncField extends Base {
  constructor(options) {
    super(options);
    /**
     * 字段ID
     */
    this.id = options.JE_CORE_RESOURCEFIELD_ID;
    /**
     * 字段编码
     */
    this.name = options.RESOURCEFIELD_CODE;
    /**
     * 字段标签
     */
    this.label = options.RESOURCEFIELD_NAME;
    /**
     * 组件类型
     */
    this.xtype = options.RESOURCEFIELD_XTYPE;
    /**
     * 默认值
     */
    this.value = options.RESOURCEFIELD_VALUE;
    /**
     * 必填
     */
    this.required = toBoolean(options.RESOURCEFIELD_REQUIRE);
    /**
     * 只读
     */
    this.disabled = toBoolean(options.RESOURCEFIELD_READONLY);
    /**
     * 禁用
     */
    // this.disabled = toBoolean(options.RESOURCEFIELD_DISABLED);
    /**
     * 隐藏
     */
    this.hidden = toBoolean(options.RESOURCEFIELD_HIDDEN);
    /**
     * 配置信息
     */
    this.configInfo = options.RESOURCEFIELD_CONFIGINFO;

    /**
     * 标签位置
     */
    this.labelAlign = options.RESOURCEFIELD_LABELALIGN || 'right';

    /**
     * 查询条件
     */
    this.querys = decode(options.RESOURCEFIELD_WHERESQL) ?? [];

    /**
     * 所属分组框
     */
    this.groupName = options.RESOURCEFIELD_GROUPNAME ?? '';
    /**
     * 排序
     */
    this.orderIndex = toNumber(options.SY_ORDERINDEX);

    /**
     * 所占列数
     */
    this.colSpan = toNumber(options.RESOURCEFIELD_COLSPAN ?? 1);
    /**
     * 内容列数
     */
    this.cols = toNumber(options.RESOURCEFIELD_COLS ?? 2);

    /**
     * 输入提示
     */
    this.placeholder = options.RESOURCEFIELD_EMPTYTEXT;
    /**
     * 标签隐藏
     */
    this.labelHidden = toBoolean(options.RESOURCEFIELD_HIDELABEL);
    /**
     * 标签颜色
     */
    this.labelColor = options.RESOURCEFIELD_LABELCOLOR;
    /**
     * 数值颜色
     */
    this.fieldColor = options.RESOURCEFIELD_FIELDCOLOR;

    /**
     * 高度
     */
    this.height = toNumber(options.RESOURCEFIELD_HEIGHT);
    /**
     * 宽度
     */
    this.width = toNumber(options.RESOURCEFIELD_WIDTH);

    /**
     * 帮助信息
     */
    this.help = {
      enable: isNotEmpty(options.RESOURCEFIELD_HELP),
      html: true,
      message: options.RESOURCEFIELD_HELP,
      width: toNumber(options.RESOURCEFIELD_HELP_TIP_W),
      height: toNumber(options.RESOURCEFIELD_HELP_TIP_H),
    };

    /**
     * 表达式
     */
    this.exps = {
      data: {
        // 绑定表达式
        exp: options.RESOURCEFIELD_BINDING,
        fn: options.RESOURCEFIELD_BINDINGFN,
      },
      visible: {
        // 显隐表达式
        exp: options.RESOURCEFIELD_INTERPRETER,
        fn: options.RESOURCEFIELD_INTERPRETERFN,
      },
      readOnly: {
        // 只读表达式
        exp: options.RESOURCEFIELD_READONLYEXP,
        fn: options.RESOURCEFIELD_READONLYEXPFN,
      },
      required: {
        // 必填表达式
        exp: options.RESOURCEFIELD_REQUIRE_EXP,
        fn: options.RESOURCEFIELD_REQUIRE_EXPFN,
      },
      select: {
        // 可选表达式
        exp: options.RESOURCEFIELD_ENABLEEXP,
        fn: options.RESOURCEFIELD_ENABLEEXPFN,
        message: options.RESOURCEFIELD_ENABLETIP,
      },
    };
    /**
     * 可选表达式
     */
    this.selectExp;
    /**
     * 启用表达式
     */
    this.expsEnable = false;
    // 提取有效表达式
    Object.keys(this.exps).forEach((key) => {
      const item = this.exps[key];
      if (item.exp || item.fn) {
        if (key === 'select') {
          this.selectExp = item;
        } else {
          this.expsEnable = true;
        }
      } else {
        delete this.exps[key];
      }
    });

    /**
     * 校验信息
     */
    this.validation = {
      regex: options.RESOURCEFIELD_REGEX, // 正则
      regexMessage: options.RESOURCEFIELD_REGEXTEXT, // 正则提示
      max: toNumber(options.RESOURCEFIELD_MAXLENGTH), // 最大值
      vtype: options.RESOURCEFIELD_VTYPE, // 校验类型
      vtypeFn: options.RESOURCEFIELD_VTYPEFN, // 自定义校验方法
    };

    /**
     * 功能ID
     */
    this.funcId = options.RESOURCEFIELD_FUNCINFO_ID;
    /**
     * 事件
     */
    this.events = parseEvents(options.RESOURCEFIELD_JSLISTENER);

    /**
     * 辅助配置项
     */
    this.otherConfig = decode(options.RESOURCEFIELD_OTHERCONFIG) ?? {};

    /**
     * 快速定位
     */
    this.anchor = false;

    /**
     *  子元素
     */
    this.children = [];

    switch (this.xtype) {
      // 编号字段
      case FuncFieldTypeEnum.INPUT_CODE.type:
        this.value = '<系统自动生成>';
        this.readOnly = true;
        this.disabled = true;
        break;

      // 子功能
      case FuncFieldTypeEnum.FUNC_CHILD.type:
        this.groupName = '';
        break;
      // 分组框
      case FuncFieldTypeEnum.FIELDSET.type:
        this.anchor = toBoolean(this.otherConfig.quickPositioning); // 定位
    }
  }

  /**
   * 字段编码
   *
   * @readonly
   * @memberof FuncField
   */
  get code() {
    return this.name;
  }

  /**
   * 字段名称
   *
   * @readonly
   * @memberof FuncField
   */
  get text() {
    return this.label;
  }

  /**
   * 只读
   *
   * @memberof FuncField
   */
  get readOnly() {
    return this.disabled;
  }
  set readOnly(readOnly) {
    this.disabled = readOnly;
  }

  addChild(data, cascade) {
    if (isPlainObject(data)) {
      data = [data];
    }
    forEach(data, (item) => {
      if (!item.isModel) {
        item = new FuncField(item);
      }
      if (this.name === item.groupName) {
        if (cascade) {
          item.addChild(data, cascade);
        }
        this.children.push(item);
      }
    });
  }
  /**
   * FormItem字段，用于展示
   * @returns
   */
  isFormItem() {
    return ![FuncFieldTypeEnum.FIELDSET.type, FuncFieldTypeEnum.FUNC_CHILD.type].includes(
      this.xtype,
    );
  }
  /**
   * bean字段，用于提取数据
   * @returns
   */
  isBeanField() {
    return ![
      FuncFieldTypeEnum.FIELDSET.type,
      FuncFieldTypeEnum.FUNC_CHILD.type,
      FuncFieldTypeEnum.FUNC_CHILD_FIELD.type,
      FuncFieldTypeEnum.DISPLAY.type,
    ].includes(this.xtype);
  }
  /**
   * 获取默认值
   * @returns
   */
  getDefaultValue() {
    if (isEmpty(this.value)) {
      if ([FuncFieldTypeEnum.INPUT_NUMBER.type].includes(this.xtype)) {
        // 防止数字必填时，给默认值校验失效
        this.value = this.required ? this.value : 0;
      }
    }
    return this.value;
  }

  /**
   * 校验规则
   */
  getRules(options) {
    const rules = [];

    // 子功能集合校验
    if (this.xtype === FuncFieldTypeEnum.FUNC_CHILD_FIELD.type) {
      rules.push({
        required: this.required,
        message: `该输入项为必填项`,
        validator: async (...args) => {
          return options.$field?.value?.validator(...args);
        },
      });
      return rules;
    }

    // 必填校验
    if (this.required) {
      rules.push({ required: true, message: `该输入项为必填项` });
    }
    // 正则校验
    if (this.validation.regex) {
      rules.push({
        pattern: new RegExp(this.validation.regex),
        message: this.validation.regexMessage,
      });
    }
    // 最大长度
    if (this.validation.max > 0) {
      rules.push({
        max: toNumber(this.validation.max),
        message: `该输入内容最大长度为${this.validation.max}字`,
      });
    }
    // 自定义校验
    switch (this.validation.vtype) {
      case 'method': // 自定义规则，写法参考ant表单规则，返回rules
        if (this.validation.vtypeFn) {
          const vtypeRules = execScript(this.validation.vtypeFn, options) ?? [];
          rules.push(...vtypeRules);
        }
        break;
      case 'unique':
        // 平台唯一值校验，后续集成...
        rules.push({
          message: `该输入项已存在，请重新输入`,
          validator: async (rule, value) => {
            if (isEmpty(value)) return true;
            return options.$func.action.baseAction.checkFieldUnique([
              { fieldCode: this.name, value },
            ]);
          },
        });
        break;
    }
    // 增加默认提示信息，防止报错
    rules.forEach((rule) => {
      rule.message = rule.message || '该输入项不符合验证规则';
    });

    return rules;
  }
}

export function parseDisplayFields(data) {
  const fields = [];
  data.forEach((item) => {
    if (!item.hidden && isEmpty(item.groupName)) {
      // 级联添加子信息
      item.addChild(data, true);
      fields.push(item);
    }
  });
  return fields;
}
